#include <iostream>
#include <string>
using namespace std;


// 虚析构和纯虚析构

namespace Animal
{
    class AnimalAbstract
    {
    private:
        /* data */
    public:
        AnimalAbstract();
        // 纯虚函数
        virtual void speak()      = 0;
        // 利用虚析构可以解决，父类指针释放子类对象时不干净的问题
        // 此为纯虚析构
        // 不管虚析构还是纯虚析构都需要代码实现
        // 存在纯虚析构时也无法实例化
        virtual ~AnimalAbstract() = 0;
    };

    AnimalAbstract::AnimalAbstract()
    {
        cout << "AnimalAbstract 构造函数调用" << endl;
    }

    AnimalAbstract::~AnimalAbstract()
    {
        cout << "AnimalAbstract 析构函数调用" << endl;
    }



    class Cat : public AnimalAbstract
    {
    private:
        string * m_Name;
    public:
        Cat(string name);
        // 纯虚函数
        virtual void speak() 
        {
            cout << * m_Name << "小猫在说话" << endl;
        }
        ~Cat();
    };

    Cat::Cat(string name)
    {
        cout << "Cat 构造函数调用" << endl;
        m_Name = new string(name);
    }

    Cat::~Cat() 
    {
        cout << "Cat 析构函数调用" << endl;
        if (m_Name != nullptr) {
            delete m_Name;
            m_Name = NULL;
        }
    }
} // namespace Animal

void test01()
{
    Animal::AnimalAbstract * animal = new Animal::Cat("Tom");
    animal->speak();
    // 父类指针在析构的时候，不会调用子类中西沟沟函数，导致子类如果有堆区属性，会出现内存泄漏！！！
    delete animal;
}

int main()
{
    test01();
    return 0;
}